import sys


def main(argv: list) -> None:
    help_msg = '''
usage:
 python3 pycrunch.py [password length] [chars for password] flags
flags:
    Output result in file
    -o [output file]

    Using source string for first password
    -s [source/last password]
'''
    use_file = False
    src = ''
    _ = 2
    count_args = len(argv)
    if count_args == 0:
        print(help_msg)
        sys.exit(0)
    
    # Обработка параметров запуска
    psw_length = argv[0]
    for i in psw_length:
        if not i.isdigit():
            print('Invalid "password length":', psw_length)
            sys.exit(1)
    psw_length = int(psw_length)

    try:
        chars = argv[1]
    except IndexError:
        print('Missing password chars')
        sys.exit(1)
    
    # Обработка необязательных параметров
    while _ < count_args:
        arg = argv[_]
        if arg == '-s':
            _ += 1
            if _ == count_args:
                print('Missing "src"')
                sys.exit(1)
            src = argv[_]
        elif arg == '-o':
            _ += 1
            if _ == count_args:
                print('Missing "output file"')
                sys.exit(1)
            filename = argv[_]
            use_file = True
        elif arg in ('-h', '--help'):
            print(help_msg)
            sys.exit(0)
        _ += 1

    if src:
        char_codes = [chars.index(i) for i in src]
        psw_num = sum([len(chars) ** i * char_codes[i] for i in range(psw_length)])
        count = pow(len(chars), psw_length)
    else:
        count = pow(len(chars), psw_length)
        char_codes = [0] * psw_length
        psw_num = 0

    max_code = len(chars) # Макс.(последний) код символа
    range_ = range(psw_length)
    num_code = char_codes[0]

    # Генерация
    if use_file:
        generate_in_output_file(psw_num, count, chars, char_codes,
                                num_code, max_code, range_, filename)
    else:
        generate_in_console(psw_num, count, chars, char_codes,
                            num_code, max_code, range_)


# Генерация с записью в файл
def generate_in_output_file(psw_num: int, count: int,
                            chars: str, char_codes: list,
                            num_code: int, max_code: int,
                            range_: range, filename: str) -> None:
    with open(filename, 'w') as f:
        while psw_num < count:
            f.write(''.join([chars[i] for i in char_codes])+'\n')
            
            # Переход на след. символ
            num_code += 1
        
            # Главный алгоритм
            if num_code == max_code:
                char_codes[0] = num_code
                for i in range_:
                    if char_codes[i] == max_code:
                        try:
                            char_codes[i+1] += 1
                        except:
                            pass
                        char_codes[i] = 0
                num_code = 0
            else:
                char_codes[0] = num_code
            
            # Счётчик
            psw_num += 1


# Генерация с выводом в консоль
def generate_in_console(psw_num: int, count: int,
                        chars: str, char_codes: list,
                        num_code: int, max_code: int,
                        range_: range) -> None:
    while psw_num < count:
        print(''.join([chars[i] for i in char_codes]))
            
        # Переход на след. символ
        num_code += 1
        
        # Главный алгоритм
        if num_code == max_code:
            char_codes[0] = num_code
            for i in range_:
                if char_codes[i] == max_code:
                    try:
                        char_codes[i+1] += 1
                    except:
                        pass
                    char_codes[i] = 0
            num_code = 0
        else:
            char_codes[0] = num_code
        
        # Счётчик
        psw_num += 1


if __name__ == '__main__':
    main(sys.argv[1:])

